using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace GenerativeAgents.Core
{
    /// <summary>
    /// 空间记忆系统
    /// 管理环境的层次化空间结构和对象位置信息
    /// </summary>
    [System.Serializable]
    public class SpatialMemory
    {
        [Header("空间记忆配置")]
        public int maxSpatialNodes = 500;
        public float spatialUpdateThreshold = 1f; // 位置变化阈值
        
        // 空间树结构
        private SpatialNode rootNode;
        private Dictionary<string, SpatialNode> spatialNodeIndex;
        private Dictionary<string, Vector3> agentLocations;
        private Dictionary<string, Vector3> objectLocations;
        private Dictionary<string, DateTime> lastUpdateTimes;
        
        // 路径缓存
        private Dictionary<string, List<Vector3>> pathCache;
        private int maxCachedPaths = 100;
        
        public SpatialMemory()
        {
            Initialize();
        }
        
        /// <summary>
        /// 初始化空间记忆
        /// </summary>
        private void Initialize()
        {
            // 创建世界根节点
            rootNode = SpatialNode.CreateWorld("GenerativeAgentWorld");
            
            // 初始化索引和缓存
            spatialNodeIndex = new Dictionary<string, SpatialNode>();
            agentLocations = new Dictionary<string, Vector3>();
            objectLocations = new Dictionary<string, Vector3>();
            lastUpdateTimes = new Dictionary<string, DateTime>();
            pathCache = new Dictionary<string, List<Vector3>>();
            
            // 将根节点添加到索引
            spatialNodeIndex[rootNode.name] = rootNode;
            
            // 创建一些默认的空间结构
            CreateDefaultSpatialStructure();
        }
        
        /// <summary>
        /// 创建默认的空间结构
        /// </summary>
        private void CreateDefaultSpatialStructure()
        {
            // 创建一些基础区域
            var mainArea = rootNode.AddChild("MainArea", Vector3.zero, new Vector3(50, 10, 50), SpatialType.Region);
            spatialNodeIndex[mainArea.name] = mainArea;
            
            // 创建子区域
            var cafArea = mainArea.AddChild("CafeArea", new Vector3(-20, 0, 0), new Vector3(15, 10, 15), SpatialType.Building);
            spatialNodeIndex[cafArea.name] = cafArea;
            
            var parkArea = mainArea.AddChild("ParkArea", new Vector3(20, 0, 0), new Vector3(20, 10, 20), SpatialType.Area);
            spatialNodeIndex[parkArea.name] = parkArea;
            
            var residentialArea = mainArea.AddChild("ResidentialArea", new Vector3(0, 0, 25), new Vector3(30, 10, 20), SpatialType.Region);
            spatialNodeIndex[residentialArea.name] = residentialArea;
            
            // 添加连接
            cafArea.AddConnection(parkArea, 1.5f, "path");
            parkArea.AddConnection(residentialArea, 2f, "path");
            cafArea.AddConnection(residentialArea, 2.5f, "path");
        }
        
        /// <summary>
        /// 更新智能体位置
        /// </summary>
        public void UpdateAgentLocation(string agentName, string locationPath, Vector3 position)
        {
            try
            {
                // 检查位置变化是否足够大
                if (agentLocations.TryGetValue(agentName, out var lastPosition))
                {
                    if (Vector3.Distance(lastPosition, position) < spatialUpdateThreshold)
                    {
                        return; // 变化太小，不更新
                    }
                }
                
                // 更新智能体位置
                agentLocations[agentName] = position;
                lastUpdateTimes[agentName] = DateTime.Now;
                
                // 查找或创建对应的空间节点
                var spatialNode = FindOrCreateSpatialNode(locationPath, position);
                
                // 从之前的位置移除智能体
                RemoveAgentFromAllNodes(agentName);
                
                // 添加智能体到新位置
                spatialNode.AddAgent(agentName);
                
                // 清理相关的路径缓存
                ClearPathCacheForAgent(agentName);
            }
            catch (Exception ex)
            {
                Debug.LogError($"[SpatialMemory] Error updating agent location for {agentName}: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 更新对象位置
        /// </summary>
        public void UpdateObjectLocation(string objectName, string locationPath, Vector3 position)
        {
            try
            {
                // 更新对象位置
                objectLocations[objectName] = position;
                lastUpdateTimes[objectName] = DateTime.Now;
                
                // 查找或创建对应的空间节点
                var spatialNode = FindOrCreateSpatialNode(locationPath, position);
                
                // 从之前的位置移除对象
                RemoveObjectFromAllNodes(objectName);
                
                // 添加对象到新位置
                spatialNode.AddObject(objectName);
            }
            catch (Exception ex)
            {
                Debug.LogError($"[SpatialMemory] Error updating object location for {objectName}: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 查找或创建空间节点
        /// </summary>
        private SpatialNode FindOrCreateSpatialNode(string locationPath, Vector3 position)
        {
            // 尝试从索引中查找
            if (spatialNodeIndex.TryGetValue(locationPath, out var existingNode))
            {
                return existingNode;
            }
            
            // 创建新的空间节点
            var newNode = CreateSpatialNodeFromPath(locationPath, position);
            spatialNodeIndex[locationPath] = newNode;
            
            return newNode;
        }
        
        /// <summary>
        /// 从路径创建空间节点
        /// </summary>
        private SpatialNode CreateSpatialNodeFromPath(string locationPath, Vector3 position)
        {
            // 解析路径
            var pathParts = locationPath.Split('/');
            SpatialNode currentNode = rootNode;
            
            for (int i = 0; i < pathParts.Length; i++)
            {
                var partName = pathParts[i];
                
                if (string.IsNullOrEmpty(partName))
                    continue;
                
                // 检查是否已存在子节点
                if (!currentNode.children.ContainsKey(partName))
                {
                    // 创建新的子节点
                    var nodeType = DetermineSpatialType(i, pathParts.Length);
                    var relativePosition = position - currentNode.position;
                    var nodeBounds = DetermineNodeBounds(nodeType);
                    
                    var childNode = currentNode.AddChild(partName, relativePosition, nodeBounds, nodeType);
                    spatialNodeIndex[partName] = childNode;
                }
                
                currentNode = currentNode.children[partName];
            }
            
            return currentNode;
        }
        
        /// <summary>
        /// 确定空间类型
        /// </summary>
        private SpatialType DetermineSpatialType(int depth, int totalDepth)
        {
            if (depth == 0) return SpatialType.Region;
            if (depth == totalDepth - 1) return SpatialType.Room;
            if (depth == totalDepth - 2) return SpatialType.Building;
            return SpatialType.Area;
        }
        
        /// <summary>
        /// 确定节点边界
        /// </summary>
        private Vector3 DetermineNodeBounds(SpatialType spatialType)
        {
            switch (spatialType)
            {
                case SpatialType.World:
                    return new Vector3(1000, 100, 1000);
                case SpatialType.Region:
                    return new Vector3(50, 10, 50);
                case SpatialType.Building:
                    return new Vector3(20, 10, 20);
                case SpatialType.Room:
                    return new Vector3(8, 3, 8);
                case SpatialType.Area:
                    return new Vector3(10, 5, 10);
                default:
                    return new Vector3(5, 3, 5);
            }
        }
        
        /// <summary>
        /// 从所有节点移除智能体
        /// </summary>
        private void RemoveAgentFromAllNodes(string agentName)
        {
            foreach (var node in spatialNodeIndex.Values)
            {
                node.RemoveAgent(agentName);
            }
        }
        
        /// <summary>
        /// 从所有节点移除对象
        /// </summary>
        private void RemoveObjectFromAllNodes(string objectName)
        {
            foreach (var node in spatialNodeIndex.Values)
            {
                node.RemoveObject(objectName);
            }
        }
        
        /// <summary>
        /// 清理智能体相关的路径缓存
        /// </summary>
        private void ClearPathCacheForAgent(string agentName)
        {
            var keysToRemove = pathCache.Keys.Where(key => key.Contains(agentName)).ToList();
            foreach (var key in keysToRemove)
            {
                pathCache.Remove(key);
            }
        }
        
        /// <summary>
        /// 查找路径
        /// </summary>
        public List<Vector3> FindPath(Vector3 start, Vector3 end)
        {
            try
            {
                var cacheKey = $"{start}_{end}";
                
                // 检查路径缓存
                if (pathCache.TryGetValue(cacheKey, out var cachedPath))
                {
                    return new List<Vector3>(cachedPath);
                }
                
                // 找到起点和终点的空间节点
                var startNode = FindNearestSpatialNode(start);
                var endNode = FindNearestSpatialNode(end);
                
                if (startNode == null || endNode == null)
                {
                    // 简单的直线路径作为后备
                    return new List<Vector3> { start, end };
                }
                
                // 使用A*算法查找路径
                var nodePath = FindNodePath(startNode, endNode);
                
                // 转换为世界坐标路径
                var worldPath = ConvertNodePathToWorldPath(nodePath, start, end);
                
                // 缓存路径
                if (pathCache.Count < maxCachedPaths)
                {
                    pathCache[cacheKey] = new List<Vector3>(worldPath);
                }
                
                return worldPath;
            }
            catch (Exception ex)
            {
                Debug.LogError($"[SpatialMemory] Error finding path from {start} to {end}: {ex.Message}");
                return new List<Vector3> { start, end };
            }
        }
        
        /// <summary>
        /// 查找最近的空间节点
        /// </summary>
        private SpatialNode FindNearestSpatialNode(Vector3 position)
        {
            SpatialNode nearestNode = null;
            float nearestDistance = float.MaxValue;
            
            foreach (var node in spatialNodeIndex.Values)
            {
                if (node.ContainsPosition(position))
                {
                    return node; // 直接包含在节点内
                }
                
                var distance = node.GetDistanceTo(position);
                if (distance < nearestDistance)
                {
                    nearestDistance = distance;
                    nearestNode = node;
                }
            }
            
            return nearestNode;
        }
        
        /// <summary>
        /// 查找节点路径
        /// </summary>
        private List<SpatialNode> FindNodePath(SpatialNode start, SpatialNode end)
        {
            if (start == end)
                return new List<SpatialNode> { start };
            
            // 简化的路径查找（实际应该使用A*算法）
            var path = new List<SpatialNode>();
            var current = start;
            var visited = new HashSet<SpatialNode>();
            
            path.Add(current);
            visited.Add(current);
            
            while (current != end && visited.Count < spatialNodeIndex.Count)
            {
                var neighbors = current.GetAccessibleNeighbors();
                SpatialNode next = null;
                float shortestDistance = float.MaxValue;
                
                foreach (var neighbor in neighbors)
                {
                    if (visited.Contains(neighbor))
                        continue;
                    
                    var distance = neighbor.GetDistanceTo(end);
                    if (distance < shortestDistance)
                    {
                        shortestDistance = distance;
                        next = neighbor;
                    }
                }
                
                if (next == null)
                    break;
                
                path.Add(next);
                visited.Add(next);
                current = next;
            }
            
            return path;
        }
        
        /// <summary>
        /// 将节点路径转换为世界坐标路径
        /// </summary>
        private List<Vector3> ConvertNodePathToWorldPath(List<SpatialNode> nodePath, Vector3 start, Vector3 end)
        {
            var worldPath = new List<Vector3> { start };
            
            foreach (var node in nodePath)
            {
                // 添加节点中心位置或适当的路径点
                if (node.waypoints.Count > 0)
                {
                    worldPath.AddRange(node.waypoints);
                }
                else
                {
                    worldPath.Add(node.position);
                }
            }
            
            worldPath.Add(end);
            return worldPath;
        }
        
        /// <summary>
        /// 获取位置的对象
        /// </summary>
        public List<string> GetObjectsAt(Vector3 location, float radius = 2f)
        {
            var objectsInRange = new List<string>();
            
            foreach (var kvp in objectLocations)
            {
                if (Vector3.Distance(kvp.Value, location) <= radius)
                {
                    objectsInRange.Add(kvp.Key);
                }
            }
            
            return objectsInRange;
        }
        
        /// <summary>
        /// 获取位置的智能体
        /// </summary>
        public List<string> GetAgentsAt(Vector3 location, float radius = 2f)
        {
            var agentsInRange = new List<string>();
            
            foreach (var kvp in agentLocations)
            {
                if (Vector3.Distance(kvp.Value, location) <= radius)
                {
                    agentsInRange.Add(kvp.Key);
                }
            }
            
            return agentsInRange;
        }
        
        /// <summary>
        /// 获取智能体当前位置
        /// </summary>
        public Vector3? GetAgentLocation(string agentName)
        {
            if (agentLocations.TryGetValue(agentName, out var location))
            {
                return location;
            }
            return null;
        }
        
        /// <summary>
        /// 获取对象当前位置
        /// </summary>
        public Vector3? GetObjectLocation(string objectName)
        {
            if (objectLocations.TryGetValue(objectName, out var location))
            {
                return location;
            }
            return null;
        }
        
        /// <summary>
        /// 获取空间节点
        /// </summary>
        public SpatialNode GetSpatialNode(string nodeName)
        {
            spatialNodeIndex.TryGetValue(nodeName, out var node);
            return node;
        }
        
        /// <summary>
        /// 获取位置描述
        /// </summary>
        public string GetLocationDescription(Vector3 position)
        {
            var nearestNode = FindNearestSpatialNode(position);
            if (nearestNode != null)
            {
                return nearestNode.GetTextDescription();
            }
            
            return $"Unknown location at {position}";
        }
        
        /// <summary>
        /// 清理过期位置信息
        /// </summary>
        public void CleanupExpiredLocations(TimeSpan maxAge)
        {
            var cutoffTime = DateTime.Now - maxAge;
            var expiredKeys = lastUpdateTimes
                .Where(kv => kv.Value < cutoffTime)
                .Select(kv => kv.Key)
                .ToList();
            
            foreach (var key in expiredKeys)
            {
                agentLocations.Remove(key);
                objectLocations.Remove(key);
                lastUpdateTimes.Remove(key);
                
                // 从空间节点中移除
                RemoveAgentFromAllNodes(key);
                RemoveObjectFromAllNodes(key);
            }
        }
        
        /// <summary>
        /// 获取节点数量
        /// </summary>
        public int GetNodeCount()
        {
            return spatialNodeIndex.Count;
        }
        
        /// <summary>
        /// 获取空间记忆统计
        /// </summary>
        public string GetSpatialStats()
        {
            return $"Spatial Nodes: {spatialNodeIndex.Count}, Agent Locations: {agentLocations.Count}, Object Locations: {objectLocations.Count}, Cached Paths: {pathCache.Count}";
        }
        
        /// <summary>
        /// 清理路径缓存
        /// </summary>
        public void ClearPathCache()
        {
            pathCache.Clear();
        }
        
        /// <summary>
        /// 获取根节点
        /// </summary>
        public SpatialNode GetRootNode()
        {
            return rootNode;
        }
        
        /// <summary>
        /// 获取所有空间节点
        /// </summary>
        public Dictionary<string, SpatialNode> GetAllSpatialNodes()
        {
            return new Dictionary<string, SpatialNode>(spatialNodeIndex);
        }
    }
}